<?php
namespace control;
// 库存报表
class inventoryReportFormClass extends adIndexClass
{
    private const title = '库存报表';
    private const page = 'inventoryReportForm';
    private array $list = ['board'=>'数据看板','cate_inventory_turnover'=>'分类库存周转率','inventory_turnover'=>'库存周转率','dull_product'=>'呆滞品占比','stock_age'=>'库龄分布','single_issue_ranking'=>'单品出库排行榜','cate_inventory_ranking'=>'分类库存排行榜'];

    /*返回网页*/
    public function home()
    {
        $root = root;
        $timeSlot = date("Y-m-d",strtotime("-1 month")).' ~ '.$this->date;
        // 搜索文本框
        $searchTxt =
            "
            <form name='mainForm' onsubmit='return false'>
                <span class='time_switching' onclick=\"timeSwitching(this,'1')\">今天</span>
                <span class='time_switching' onclick=\"timeSwitching(this,'2')\">昨天</span>
                <span class='time_switching' onclick=\"timeSwitching(this,'3')\">本周</span>
                <span class='time_switching' onclick=\"timeSwitching(this,'4')\">本月</span>".
                text([
                    'name'    => 'date',
                    'title'   => "时间段",
                    "class"   => "text text-data contour width200",
                    "value"   =>  $timeSlot,
                    'laydate' => ['range' => '~', 'type' => 'date',],
                ]).
                "<input class='searchSub' type='button' onclick='cardSearch()' value='查询'>
            </form>";

        //$record = query('user_setting',"stid = '".self::$stid."' and type = '库存报表'");
        $setting = ["board", "cate_inventory_turnover", "inventory_turnover", "dull_product", "stock_age", "single_issue_ranking", "cate_inventory_ranking"];
        $board = in_array('board',$setting)?'display:block;':'display:none;';
        $cate_inventory_turnover = in_array('cate_inventory_turnover',$setting)?'display:block;':'display:none;';
        $inventory_turnover = in_array('inventory_turnover',$setting)?'display:block;':'display:none;';
        $dull_product = in_array('dull_product',$setting)?'display:block;':'display:none;';
        $stock_age = in_array('stock_age',$setting)?'display:block;':'display:none;';
        $single_issue_ranking = in_array('single_issue_ranking',$setting)?'display:block;':'display:none;';
        $cate_inventory_ranking = in_array('cate_inventory_ranking',$setting)?'display:block;':'display:none;';

        $dull_product_tip = componentClass::tipComponent('呆滞品指有库存且近X天没有出库记录的商品','?');
        $turnover_tip = componentClass::tipComponent('库存周转率=本期出库金额/[(期初库存金额+期末库存金额)/2]','?');
        $pick_tip = componentClass::tipComponent('仓库原材料领用率=领用数量（领料出库单）/(期初数量+入库数量)','?');
        $pick_complete_tip = componentClass::tipComponent('领料完成率=实际领料数量（领料出库单）/计划领料数量','?');
        $html = <<<EOT
        <div class="home-warp">
                <div class="spread-box">
                <div class="search">$searchTxt</div>
                <form name="sortForm">
                    <input type="hidden" name="field" value="">
                    <input type="hidden" name="sort" value="">
                </form>
                 </div>
             <div class="box-content">
                 <div class="flex-div">
                    <div class="flex-div-children data-widget" style="{$board}">
                        <div class="frame-title"><span class="title-card">数据看板</span></div>
                        <ul class="revenue" id="boardHtml">
                            <li class="vertical-line">
                                <div class="title-card-li-content">
                                   <div>期初库存金额</div>
                                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                                <div class="title-card-li-content">
                                   <div>入库金额</div>
                                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                                 <div class="title-card-li-content">
                                   <div>出库金额</div>
                                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                                 <div class="title-card-li-content">
                                   <div>期末库存金额</div>
                                   <div><span class="title-card-li-money">￥0.00</span><span>万</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                             <div class="title-card-li-content">
                                   <div>库存周转率{$turnover_tip}</div>
                                   <div><span class="title-card-li-money">0</span><span>次</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                             <div class="title-card-li-content">
                                   <div>原材料领用率{$pick_tip}</div>
                                   <div><span class="title-card-li-money">0</span><span>%</span></div>
                                </div>
                            </li>
                            <li class="vertical-line">
                             <div class="title-card-li-content">
                                   <div>领料完成率{$pick_complete_tip}</div>
                                   <div><span class="title-card-li-money">0</span><span>%</span></div>
                                </div>
                            </li>
                        </ul>
                    </div>
                    </div>
                    <div class="flex-div">
                        <div class="flex-div-children data-widget" style="{$cate_inventory_turnover}">
                            <div class="frame-title"><span class="title-card">分类库存周转率</span></div>
                            <div class="data-box-show" id="cateInventoryTurnoverHtml"></div>
                        </div>
                         <div class="flex-div-children colum-line"></div>
                        <div class="flex-div-children data-widget" style="{$stock_age}">
                            <div class="frame-title"><span class="title-card">库龄分布</span></div>
                            <div class="data-box-show" id="stockAgeHtml"></div>
                        </div>
                    </div>
                     <div class="flex-div">
                         <div class="flex-div-children data-widget" style="{$dull_product}">
                            <div class="frame-title"><span class="title-card">呆滞品占比</span>{$dull_product_tip}</div>
                            <div class="data-box-show" id="dullProductHtml"></div>
                        </div>
                         <div class="flex-div-children colum-line"></div>
                        <div class="flex-div-children data-widget" style="{$inventory_turnover}">
                            <div class="frame-title"><span class="title-card">库存周转率趋势</span></div>
                            <div class="data-box-show" id="inventoryTurnoverHtml"></div>
                        </div>
                    </div>
                    <div class="flex-div">
                        <div class="flex-div-children data-widget" style="{$cate_inventory_ranking}">
                           <div class="frame-title"><span class="title-card">分类库存排行榜</span></div>
                           <div id="cateInventoryRankingHtml"></div>
                        </div>
                        <div class="flex-div-children colum-line"></div>
                        <div class="flex-div-children data-widget" style="{$single_issue_ranking}">
                           <div class="frame-title"><span class="title-card">单品出库排行榜</span></div>
                           <div id="singleIssueRankingHtml"></div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>
     <script src='{$this->root}static/javascript/echarts.min.js'></script>
<script>
function timeSwitching(e,type) {
    $('.time_switching').removeClass('time-choice')
    $(e).addClass('time-choice')
    $.post(root + "control/adIndex.html?cla=salesReportForm&fun=timeSwitching", {type:type}, function (data) {
         $("[name='date']").val(data.date);
         cardSearch();
    }, "json");
}
function search_line(form,cla,fun) {
     $("#" + fun + "Html").html("数据查询中，请稍后。。。");
     //串联表单
        var formName = form.split(",");
        var serialize = "";
        var a = "";
        for (var i = 0; i < formName.length; i++) {
            if (serialize == "") {
                a = "";
            } else {
                a = "&";
            }
            if (formName[i] != "") {
                serialize += a + $("[name=" + formName[i] + "]").serialize();
            }
        }
    $.post(root + "control/adIndex.html?cla=" + cla + "&fun=" + fun, serialize, function (data) {
         $("#" + fun + "Html").html(data.html);
    }, "json");
}
function dataSort(obj) {
    $("[name='field']").val($(obj).data('field'))
    $("[name='sort']").val($(obj).data('sort'))
    search_line('mainForm,sortForm',$(obj).data('cla'),$(obj).data('fun'))
}


/**
* 看板搜索
*/
function cardSearch(){
      ['board', 'cateInventoryTurnover', 'inventoryTurnover', 'dullProduct', 'stockAge', 'singleIssueRanking', 'cateInventoryRanking'].forEach((fun)=>{
                    search_line('mainForm','inventoryReportForm', fun)
    })
}

$(function() {
    ['board', 'cateInventoryTurnover', 'inventoryTurnover', 'dullProduct', 'stockAge', 'singleIssueRanking', 'cateInventoryRanking'].forEach((fun)=>{
                    search_line('mainForm','inventoryReportForm', fun)
    });
})


</script>
EOT;
        $style = '<style>
            .time-choice{background-color: #6aacfb!important;color: #eee}
            #boardHtml{height: 130px;}
            .title-card-li-content{
              text-align: center;
            }
            .title-card-li-money{
              font-size: 17px;font-weight: bold
            }
            .time_switching{
                display: inline-block;
                width: 80px;
                height: 26px;
                line-height: 26px;
                background-color: #e6e6e6;
                text-align: center;
                margin-right: 15px;
                cursor: pointer;
            }
            .text-data{
                margin-right: 15px;
            }
            .home-warp{flex-direction: column}
            .left-box, .right-box {margin: 0;}
            .left-box{width: 71.5%;}
            .right-box{flex: 1}
            .left-box .flex-div,.right-box .flex-div {margin: 0 10px 10px 0;}
            .colum-line{width: 10px;flex: 0 0 auto}
            .flex-div > .data-widget:nth-child(2n-1){margin-right: 0}
            .home-warp .flex-div-children ul{padding-right: 0}
            .search {padding: 10px 10px 0 10px;}
            .m-b-10{margin-bottom: 10px;}
            .revenue{display: flex;align-items: center;}
            .vertical-line{width: 100%;padding-left: 0!important;min-height: 100px;}
            .right-box-ul{
                max-height: none;
             }
             .right-box-title{
                display: flex;
                justify-content: space-around;
             }
             .right-text{
                height: auto;
             }
             .right-box-title li{
                float: left;
                margin: 5px 10px;
                width: 20%;
                text-align: left;
                line-height: 1;
             }
             .data-widget-select{
                margin-right: 10px;
             }
             .data-widget-select .fs-label{
                 height: 15px;line-height: 15px;
             }
             .data-widget-select .fs-label-wrap{
                 border-radius: 4px;
             }
             .aim-rank li{
                margin: 5px 0;
             }
             .aim-rank span{
                display: inline-block;
                width: 100%;
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                -o-text-overflow:ellipsis;
             }
             /*.aim-rank .right-box-title li:nth-child(1){min-width: 40px}
             .aim-rank .right-box-title li:nth-child(2){width: 50px}
             .aim-rank .right-box-title li:nth-child(3){width: 80px}
             .aim-rank .right-box-title li:nth-child(4){width: 80px}*/
</style>';
        return head("ad") . $style . $this->adheader($this->getOnion()) . $html . warn() . $this->adfooter();
    }

    /**
     * 单品出库排行榜
     */
    public function singleIssueRanking(): bool|string
    {
        $date = $this->post('date');
        $field = $this->post('field');
        $sort = $this->post('sort');
        $where = '';
        if (!empty($date)) {
            $where .= $this->timeComparison($date, 'date', 'inv.confirmTime');
        }

        $sortArr = ['num'=>'desc','money'=>'desc'];
        if($field && in_array($field,array_keys($sortArr))){
            $order = " order by $field $sort ";
            $sortArr[$field] = $sort=='asc'?'desc':'asc';
        }else{
            $order = " order by num desc ";
            $sortArr['num'] = 'asc';
        }
        //数据查询
        $sql = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " materialId,ifnull(sum(mx.num),0) as num,ifnull(sum(mx.money),0) as money ",
            "where" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 {$where} group by mx.materialId {$order} limit 10"
        ));
        //可排序按钮
        $num = salesReportFormClass::sortButton(['text'=>'出库数量','sort'=>$sortArr['num'],'field'=>'num','cla'=>'inventoryReportForm','fun'=>'singleIssueRanking']);
        $money = salesReportFormClass::sortButton(['text'=>'出库金额','sort'=>$sortArr['money'],'field'=>'money','cla'=>'inventoryReportForm','fun'=>'singleIssueRanking']);
        $ul = '<ul class="right-box-ul aim-rank">';
        if (!$sql['array']) {
            $ul .= '<li class="nodata">暂无内容</li>';
        } else {
            $ul .= "<li><ul class='right-box-title'><li>排名</li><li>物料名称</li>{$num}{$money}<li>金额总占比</li></ul></li>";
            $result = find(array(
                "table"=>"inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field"=>"ifnull(sum(mx.money),0) as money",
                "where"=>" 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 {$where} group by mx.materialId "));
            $outMoneyTotal = array_sum(array_column((array)$result['array'],'money'));
            foreach ($sql['array'] as $index => $array) {
                $material = query("material"," id = '$array[materialId]' ","name");
                $proportion = $outMoneyTotal>0?round($array['money']/$outMoneyTotal*100,1):0;
                $ul .= "
                        <li>
                            <ul class='right-box-title'>
                                <li>" . ($index + 1) . "</li>
                                <li>" . zishu($material['name'],10) . "</li>
                                <li>".($array['num']?self::lostZero($array['num'],'numPrecision'):0)."</li>
                                <li>".($array['money']?self::lostZero($array['money']):0)."</li>
                                <li>".$proportion."%</li>
                            </ul>
                        </li>";
            }
        }
        $ul .= '</ul>';
        // 拼接字符串
        $json['html'] = $ul;
        return json_encode($json, 320);
    }

    /**
     *分类库存排行榜
     */
    public function cateInventoryRanking(): bool|string
    {
        $date = $this->post('date');
        $field = $this->post('field');
        $sort = $this->post('sort');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = $this->date;
            $timeArr[1] = $this->date;
        }

        $sortArr = ['num'=>'desc','money'=>'desc'];
        if($field && in_array($field,array_keys($sortArr))){
            $sortArr[$field] = $sort=='asc'?'desc':'asc';
            $sort_order = $sort=='asc'?SORT_ASC:SORT_DESC;
        }else{
            $sortArr['num'] = 'asc';
            $field = 'num';
            $sort_order = SORT_DESC;
        }
        $res = [];
        //库存金额=入库-出库
        $inMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' "
        ))['money'];
        $outMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' "
        ))['money'];
        $total = $inMoney - $outMoney;
        //数据查询
        $type = find(array("table" => "material_type", "field" => " id,name ", "where" => " 1=1 and coid = '".self::$coid."' and pid = 0 order by list"));
        foreach ($type['array'] as $val){
            $data['where'] = " pid='{$val['id']}' ";
            $and = " and mx.materialId in (select id from material where typePath like '%".$val['id']."%') ";
            $in = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.num),0) as num,ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' {$and} "
            ));
            $out = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.num),0) as num,ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' {$and} "
            ));
            $terminalInventory = $in['money'] - $out['money'];
            $terminalInventoryNum = $in['num'] - $out['num'];
            $res[] = [
                'type'=>$val['name'],
                'num'=>$terminalInventoryNum,
                'money'=>$terminalInventory,
            ];
        }
        $res = self::my_sort($res,$field,$sort_order); //数组排序
        $res = array_slice($res,0,10);  //前10
        //可排序按钮
        $num = salesReportFormClass::sortButton(['text'=>'库存数量','sort'=>$sortArr['num'],'field'=>'num','cla'=>'inventoryReportForm','fun'=>'cateInventoryRanking']);
        $money = salesReportFormClass::sortButton(['text'=>'库存金额','sort'=>$sortArr['money'],'field'=>'money','cla'=>'inventoryReportForm','fun'=>'cateInventoryRanking']);
        $ul = '<ul class="right-box-ul aim-rank">';
        if (!$res) {
            $ul .= '<li class="nodata">暂无内容</li>';
        } else {
            $ul .= "<li><ul class='right-box-title'><li>排名</li><li>物料分类</li>{$num}{$money}<li>金额占比累计</li></ul></li>";
            $grand_total = 0;
            foreach ($res as $index => $array) {
                $proportion = $total>0?round(($array['money']+$grand_total)/$total*100,1):0;
                $ul .= "<li><ul class='right-box-title'><li>" . ($index + 1) . "</li><li>" . zishu($array['type'],10) . "</li><li>".($array['num']?self::lostZero($array['num'],'numPrecision'):0)."</li><li>".($array['money']?self::lostZero($array['money']):0)."</li><li>".$proportion."%</li></ul></li>";
                $grand_total += $array['money'];
            }
        }
        $ul .= '</ul>';
        // 拼接字符串
        $json['html'] = $ul;
        return json_encode($json, 320);
    }
    public static function getMaterialTypeAll($data = []): string
    {
        // 条件
        $data['where'] = $data['where'] ?? " pid='0' ";
        // 结果
        $result = find(['table' => 'material_type', 'where' => $data['where'] . " and coid = '" . self::$coid . "' order by list asc,time asc"]);
        $temp = '';
        if ($result['array']) {
            foreach ($result['array'] as $value) {
                // 判断下级是否存在
                $data['where'] = " pid='{$value['id']}' and coid = '".self::$coid."' ";
                $has = query('material_type', $data['where']);
                if ($has['id']) {
                    $temp .= $value['id'].',';
                    $temp .= self::getMaterialTypeAll($data);
                } else {
                    $temp .= $value['id'].',';
                }
            }
        }
        return rtrim($temp,',');
    }
    /**
     * 分类库存周转率 - 返回数据
     *
     */
    public function cateInventoryTurnover(): bool|string
    {
        $date = $this->post('date');
        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = $this->date;
            $timeArr[1] = $this->date;
        }
        $arr = find(array("table"=>"material_type","field"=>"id,name","where"=>" coid = '".self::$coid."' and pid = 0 order by list asc "));
        $res = [];
        foreach ($arr['array'] as $index => $array) {
            $and = " and mx.materialId in (select id from material where typePath like '%".$array['id']."%') ";
            //期初库存金额
            $inMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') < '$timeArr[0]' {$and} "
            ))['money'];
            $outMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') < '$timeArr[0]' {$and} "
            ))['money'];
            $openingInventory = $inMoney - $outMoney;
            //出库金额
            $where = "";
            if ($date) {
                $where .= $this->timeComparison($date, 'date', 'inv.confirmTime');
            }
            $putOutMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 {$and} {$where} "
            ))['money'];
            //期末库存金额
            $inMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' {$and} "
            ))['money'];
            $outMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' {$and} "
            ))['money'];
            $terminalInventory = $inMoney - $outMoney;
            //库存周转率
            $dividend = ((float)$openingInventory+(float)$terminalInventory)/2;
            $turnover = ($dividend > 0 ? round(((float)$putOutMoney / $dividend) * 100, 1) : 0);
            $res[] = [
                'text'  => $array['name'],
                'rate' => $turnover,
            ];

        }
        $data = [
            "name" => array_column($res,'text'),
            "series" => [
                [
                    'name' => '分类库存周转率',
                    'data' => array_column($res,'rate')
                ],
            ]
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }


    /**
     * 库存周转率趋势 数据
     */
    public function inventoryTurnover(): bool|string
    {
        $date = $this->post('date');

        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = date('Y-m-d', strtotime("-6 day"));
            $timeArr[1] = $this->date;
        }

        $m = $timeArr[0];
        $res   = [];
        while($m <= $timeArr[1]){
            //期初库存金额
            $inMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') < '$m' "
            ))['money'];
            $outMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') < '$m' "
            ))['money'];
            $openingInventory = $inMoney - $outMoney;
            //出库金额
            $where = "";
            if ($date) {
                $where .= " and date_format(inv.confirmTime, '%Y-%m-%d') = '$m' ";
            }
            $putOutMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 {$where} "
            ))['money'];
            //期末库存金额
            $inMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$m' "
            ))['money'];
            $outMoney = find(array(
                "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
                "field" => " ifnull(sum(mx.money),0) as money ",
                "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$m' "
            ))['money'];
            $terminalInventory = $inMoney - $outMoney;
            //库存周转率
            $dividend = ((float)$openingInventory+(float)$terminalInventory)/2;
            $turnover = ($dividend > 0 ? round(((float)$putOutMoney / $dividend) * 100, 1) : 0);
            $res[] = [
                'date'     => date("m月d日",strtotime($m)),
                'rate' => $turnover,
            ];
            $m = date("Y-m-d",strtotime($m." +1 day"));
        }
        $data = [
            "name" => array_column($res,'date'),
            "series" => [
                [
                    'name' => '',
                    'data' => array_column($res,'rate')
                ],
            ]
        ];
        $json['html'] = $this->curve($data);
        return json_encode($json, 320);
    }

    /**
     * 呆滞品占比 - 返回数据
     */
    public function dullProduct(): bool|string
    {
        $days = para('deadDays');  //呆滞天数
        //库存金额=入库-出库
        $in = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.num),0) as num,ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 "
        ));
        $out = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.num),0) as num,ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 "
        ));
        $allMoney = $in['money'] - $out['money'];

        $dullProduct = find(array(
            "table"=>"(select * from inventory_record order by time) as a",
            "field"=>"
            any_value(a.time) as time,
            a.materialId,
            a.batch,
            any_value(ifnull(sum(a.num),0)) as num
            ",
            "where"=>" 
            a.coid = '".self::$coid."' 
            and if(
            (SELECT time FROM inventory_record WHERE materialId = a.materialId and batch = a.batch and coid = '".self::$coid."' and num < 0 ORDER BY time DESC LIMIT 1) is null,
            DATEDIFF(now(),a.time) > {$days},
            DATEDIFF(now(),(SELECT time FROM inventory_record WHERE materialId = a.materialId and batch = a.batch and coid = '".self::$coid."' and num < 0 ORDER BY time DESC LIMIT 1)) > {$days})
             group by a.materialId,a.batch having sum(a.num) > 0 "));
        $dullProductMoney = 0;
        foreach ((array)$dullProduct['array'] as $arr){
            $price = inventoryDefaultClass::getInventoryPrice($arr['materialId']);
            $dullProductMoney += self::formattingFigure($price*$arr['num']);
        }
        //金额占比
        $series = [
            ['name' => '呆滞品', 'data' => round($dullProductMoney / 10000, 2)],
            ['name' => '非呆滞品', 'data' => round(($allMoney - $dullProductMoney) / 10000, 2)],
        ];
        $data         = [
            "text" => '金额占比',
            "subtext" => '单位：万元',
            "series" => $series,
        ];
        $json['html'] = "<div style='display: inline-block;width: 49%;height: 100%'>".$this->pie($data)."</div>";

        $allNum =  $in['num'] - $out['num'];
        $dullProductNum = array_sum((array)array_column($dullProduct['array'],'num'));
        //数量占比
        $series = [
            ['name' => '呆滞品', 'data' => $dullProductNum],
            ['name' => '非呆滞品', 'data' => $allNum - $dullProductNum],
        ];
        $data         = [
            "text" => '数量占比',
            "subtext" => '',
            "color" => ['#fac858','#91cc75'],
            "series" => $series,
        ];
        $json['html'] .= "<div style='display: inline-block;width: 49%;height: 100%'>".$this->pie($data)."</div>";
        return json_encode($json, 320);
    }

    /**
     * 库龄分布 - 返回数据
     *
     */
    public function stockAge(): bool|string
    {
        $arr = ['未到期','0-30天','30-60天','60-90天','90天以上'];
        $res = [];
        foreach ($arr as $index => $text) {
            $where = "";
            switch ($index){
                case 0:
                    $where = " and DATEDIFF(now(),a.time) <= 0 ";
                    break;
                case 1:
                    $where = " and DATEDIFF(now(),a.time) > 0 and DATEDIFF(now(),a.time) <= 30 ";
                    break;
                case 2:
                    $where = " and DATEDIFF(now(),a.time) > 30 and DATEDIFF(now(),a.time) <= 60 ";
                    break;
                case 3:
                    $where = " and DATEDIFF(now(),a.time) > 60 and DATEDIFF(now(),a.time) <= 90 ";
                    break;
                case 4:
                    $where = " and DATEDIFF(now(),a.time) > 90 ";
                    break;
            }
            $result = find(array(
                "table"=>"inventory_record as a",
                "field"=>"
                any_value(a.time) as time,
                a.materialId,
                a.batch,
                any_value(ifnull(sum(a.num),0)) as num
                ",
                "where"=>" a.coid = '".self::$coid."' {$where} group by a.materialId,a.batch having sum(a.num) > 0 "));
            $total = 0;
            foreach ((array)$result['array'] as $arr){
                $price = inventoryDefaultClass::getInventoryPrice($arr['materialId']);
                $total += self::formattingFigure($price*$arr['num']);
            }
            $res[] = [
                'text'  => $text,
                'money' => round($total / 10000, 2),
            ];
        }
        $data = [
            "subtext" => '单位：万元',
            "name" => array_column($res,'text'),
            "series" => [
                [
                    'name' => '库龄分布',
                    'data' => array_column($res,'money')
                ],
            ]
        ];
        $json['html'] = $this->barCharts($data);
        return json_encode($json, 320);
    }


    /**
     * 数据看板
     */
    public function board(): bool|string
    {
        $json['html'] = '';
        $root = $this->root;
        $date = $this->post('date');

        if (!empty($date)) {
            $timeArr = explode(' ~ ', $date);
        } else {
            $timeArr[0] = $this->date;
            $timeArr[1] = $this->date;
        }
        //期初库存金额
        $inMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') < '$timeArr[0]' "
        ))['money'];
        $outMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') < '$timeArr[0]' "
        ))['money'];
        $openingInventory = $inMoney - $outMoney;
        $money = self::convertToTenThousand($openingInventory);
        $json['html'] .= <<<efo
                        <li class="vertical-line" onclick="newIframe('收发汇总表','{$root}control/adIndex.html?cla=receiptDeliverySummary&fun=home')">
                            <div class="title-card-li-content">
                               <div>期初库存金额</div>
                               <div><span class="title-card-li-money">￥{$money['amount']}</span><span>{$money['unit']}</span></div>
                            </div>
                        </li>
         
efo;
        //入库金额
        $where = "";
        if ($date) {
            $where .= $this->timeComparison($date, 'date', 'inv.confirmTime');
        }
        $putInMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 {$where} "
        ))['money'];
        //核销单
        $money = self::convertToTenThousand($putInMoney);
        $json['html'] .= <<<efo
                        <li class="vertical-line" onclick="newIframe('收发汇总表','{$root}control/adIndex.html?cla=receiptDeliverySummary&fun=home')">
                            <div class="title-card-li-content">
                                <div>入库金额</div>
                                <div><span class="title-card-li-money">￥{$money['amount']}</span><span>{$money['unit']}</span></div>
                            </div>
                        </li>
         
efo;
        //出库金额
        $where = "";
        if ($date) {
            $where .= $this->timeComparison($date, 'date', 'inv.confirmTime');
        }
        $putOutMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 {$where} "
        ))['money'];
        //核销单
        $money = self::convertToTenThousand($putOutMoney);
        $json['html'] .= <<<efo
                        <li class="vertical-line" onclick="newIframe('收发汇总表','{$root}control/adIndex.html?cla=receiptDeliverySummary&fun=home')">
                            <div class="title-card-li-content">
                                <div>出库金额</div>
                                <div><span class="title-card-li-money">￥{$money['amount']}</span><span>{$money['unit']}</span></div>
                            </div>
                        </li>
         
efo;
        //期末库存金额
        $inMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已入库','已复核') and inv.classify = 1 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' "
        ))['money'];
        $outMoney = find(array(
            "table" => "inventory_changes_detail as mx join inventory_changes as inv on mx.orderId = inv.id",
            "field" => " ifnull(sum(mx.money),0) as money ",
            "single" => " 1=1 and mx.coid = '".self::$coid."' and inv.state in ('已出库','已复核') and inv.classify = 0 and date_format(inv.confirmTime, '%Y-%m-%d') <= '$timeArr[1]' "
        ))['money'];
        $terminalInventory = $inMoney - $outMoney;
        $money = self::convertToTenThousand($terminalInventory);
        $json['html'] .= <<<efo
                        <li class="vertical-line" onclick="newIframe('收发汇总表','{$root}control/adIndex.html?cla=receiptDeliverySummary&fun=home')">
                            <div class="title-card-li-content">
                                <div>期末库存金额</div>
                                <div><span class="title-card-li-money">￥{$money['amount']}</span><span>{$money['unit']}</span></div>
                            </div>
                        </li>
         
efo;
        //库存周转率
        $dividend = ((float)$openingInventory+(float)$terminalInventory)/2;
        $turnover = ($dividend > 0 ? round(((float)$putOutMoney / $dividend) * 100, 1) : 0);
        $turnover_tip = componentClass::tipComponent('库存周转率=本期出库金额/[(期初库存金额+期末库存金额)/2]','?');
        $json['html'] .= <<<efo
                        <li class="vertical-line no-hover">
                            <div class="title-card-li-content">
                                <div>库存周转率{$turnover_tip}</div>
                                <div><span class="title-card-li-money">{$turnover}</span><span>%</span></div>
                            </div>
                        </li>
         
efo;
        $where = "";
        if ($date) {
            $where .= $this->timeComparison($date, 'date', 'b.confirmTime');
        }
        $pickNum = find(
            array(
                "table"=>"inventory_changes_detail as a left join inventory_changes as b on a.orderId = b.id join material as c on a.materialId = c.id",
                "field"=>"ifnull(sum(a.num),0) as num",
                "single"=>" 1=1 and a.coid = '".self::$coid."' and b.classify = 0 and c.subject = '原材料' and b.state in ('已出库','已复核') {$where} "
            )
        )['num']?:0;
        $opening = find(
            array(
                'field' => " ifnull(sum(a.num),0) as num ",
                'table' => 'inventory_record as a join material as b on a.materialId = b.id',
                'single' => " a.coid = '".self::$coid."' and date_format(a.time, '%Y-%m-%d') < '$timeArr[0]' and b.subject = '原材料' "
            )
        )['num']?:0;
        $putInNum = find(
            array(
                "table"=>"inventory_changes_detail as a left join inventory_changes as b on a.orderId = b.id join material as c on a.materialId = c.id",
                "field"=>"ifnull(sum(a.num),0) as num",
                "single"=>" 1=1 and a.coid = '".self::$coid."' and b.classify = 1 and b.state in ('已入库','已复核') and c.subject = '原材料' {$where} "
            )
        )['num']?:0;
        $pick_tip = componentClass::tipComponent('仓库原材料领用率=领用数量（领料出库单'.self::lostZero($pickNum,'numPrecision').'）/(期初数量'.self::lostZero($opening,'numPrecision').'+入库数量'.self::lostZero($putInNum,'numPrecision').')','?');
        $pickRate = ($opening+$putInNum)>0?round($pickNum/($opening+$putInNum)*100,2):0;
        $json['html'] .= <<<efo
                        <li class="vertical-line no-hover">
                            <div class="title-card-li-content">
                                <div>原材料领用率{$pick_tip}</div>
                                <div><span class="title-card-li-money">{$pickRate}</span><span>%</span></div>
                            </div>
                        </li>
         
efo;


        $where = "";
        if ($date) {
            $where .= $this->timeComparison($date, 'date', 'recordDate');
        }
        //需求数量
        $machining_demands = find(
            array(
                'field' => " ifnull(sum(a.num),0) as quantity ",
                'table' => 'machining_demands as a join machining_order as b on a.sourceId = b.id join material as c on c.id = a.materialId ',
                'single' => " a.coid = '".self::$coid."' and b.state = '已确认' {$where} "
            )
        )['quantity']?:0;
        $completeRate = $machining_demands>0?round($pickNum/$machining_demands*100,2):0;
        $pick_complete_tip = componentClass::tipComponent('领料完成率=实际领料数量（领料出库单'.self::lostZero($pickNum,'numPrecision').'）/计划领料数量'.self::lostZero($machining_demands,'numPrecision').'','?');
        $json['html'] .= <<<efo
                        <li class="vertical-line no-hover">
                            <div class="title-card-li-content">
                                <div>领料完成率{$pick_complete_tip}</div>
                                <div><span class="title-card-li-money">{$completeRate}</span><span>%</span></div>
                            </div>
                        </li>
         
efo;

        return json_encode($json, 320);
    }
    /**
     * 饼图模板
     *
     * @param array $data 格式如上
     */
    public function pie($data)
    {
        $series = $legend = '';
        foreach ($data['series'] as $key => $array) {
            $legend .= "'{$array['name']}',";
            $value  = (is_array($array['data']) ? $array['data'][0] : $array['data']);
            $series .= '{value:"' . $value . '", name: "' . $array['name'] . '"},';
        }
        $color = "";
        if(isset($data['color'])){
            $color .= "color:[";
            foreach ($data['color'] as $v){
                $color .= "'{$v}',";
            }
            $color .= "],";
        }
        $option = <<<EOT
        var option = {
            legend: {
                data: [{$legend}]
            },
            tooltip: {
                trigger: 'item'
            },
            legend: {
                left: 'center',
                top: '5%',
            },
            title: {
                text: '{$data['text']}',
                subtext: '{$data['subtext']}',
                left: 'center',
                top: '55%'
            },
            {$color}
            series: [
                {
                    name: '',
                    type: 'pie',
                    radius: ['35%', '60%'],
                    center: ['50%', '60%'],
                    labelLine: {
                        length: '5%',
                    },
                    itemStyle: {
                        borderColor: '#fff',
                        borderWidth: 2
                    },
                    label: {
                        formatter: '{c}/{d}%',
                        // formatter: '{b}：{c}',
                    },
                    data: [{$series}]
                }
            ]
        };
EOT;
        //返回
        return $this->echarts($option);
    }

}
